﻿// libeventDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//#include "event2/event-config.h"
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <unistd.h>
#endif

#include "event2/event.h"
#include "event2/util.h"
#include "event2/event_compat.h"
#include "event2/event_struct.h"
#include "event2/bufferevent.h"
#include "event2/thread.h"

#include <event2/buffer.h>
#include <event2/listener.h>
#include <thread>

static void conn_writecb(struct bufferevent* bev, void* user_data)
{
	struct evbuffer* output = bufferevent_get_output(bev);
	if (evbuffer_get_length(output) == 0) {
		printf("flushed answer finish\n");
		//bufferevent_free(bev);
	}
	else {
		printf("send pending\n");
	}
}
static void conn_readcb(struct bufferevent* bev, void* user_data)
{
	char buf[128] = {0};
	int readlen = bufferevent_read(bev, buf, 127);
	printf("recv,len:%d,data:%s\n", readlen, buf);

	char sendbuf[128] = { 0 };
	sprintf_s(sendbuf, sizeof(sendbuf), " ack %s", buf);
	bufferevent_write(bev, sendbuf, strlen(sendbuf) + 1);
}
static void conn_eventcb(struct bufferevent* bev, short events, void* user_data)
{
	printf("conn_eventcb events:%x\n", events);
	if (events & BEV_EVENT_EOF) {
		printf("Connection closed.\n");
	}
	else if (events & BEV_EVENT_ERROR) {
		printf("Got an error on the connection: %s\n",
			strerror(errno));/*XXX win32*/
	}
	
	/* None of the other events can happen here, since we haven't enabled
	 * timeouts */
	bufferevent_free(bev);
}


static void accept_cb(evutil_socket_t fd, short events, void* arg)
{
	evutil_socket_t sockfd;

	struct sockaddr_in client;
	socklen_t len = sizeof(client);

	sockfd = ::accept(fd, (struct sockaddr*)&client, &len);
	evutil_make_socket_nonblocking(sockfd);

	printf("accept a client %d\n", sockfd);

	struct event_base* base = (event_base*)arg;

	//动态创建一个event结构体，并将其作为回调参数传递给
	//struct event* ev = event_new(NULL, -1, 0, NULL, NULL);
	//event_assign(ev, base, sockfd, EV_READ | EV_PERSIST, socket_read_cb, (void*)ev);
	struct event* ev = event_new(base, sockfd, EV_READ | EV_PERSIST, socket_read_cb, (void*)ev);

	event_add(ev, NULL);
}


int tcpServer_main2()
{
#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);

	evthread_use_windows_threads();
#endif
	struct event_base *base = event_base_new();
	if (!base) {
		fprintf(stderr, "Could not initialize libevent!\n");
		return 1;
	}

	struct sockaddr_in sin = { 0 };
	sin.sin_family = AF_INET;
	sin.sin_port = htons(8001);
	//sin.sin_addr.s_addr = inet_addr(m_szAddress);

	SOCKET lsocket = socket(AF_INET, SOCK_STREAM, 0);
	//允许多次绑定同一个地址。要用在socket和bind之间  
	evutil_make_listen_socket_reuseable(lsocket);

	bind(lsocket, (const struct sockaddr*)&sin, sizeof(sin));
	listen(lsocket, 10);

	struct  event* ev_listen = event_new(base, lsocket, EV_READ | EV_PERSIST, accept_cb, base);
	event_add(ev_listen, NULL);

	printf("start waiting 8000.\n");
	event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);

	return 0;
}
